import { ConfigEnv, loadEnv, PluginOption, UserConfigExport } from 'vite'
import vue from '@vitejs/plugin-vue'
import eslintPlugin from 'vite-plugin-eslint'
import viteSvgIcons from 'vite-plugin-svg-icons'
import { viteMockServe } from 'vite-plugin-mock'
import path from 'path'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { ElementPlusThemePlugin } from '@pzy915/vite-plugin-element-plus-theme'
import visualizer from 'rollup-plugin-visualizer'
import viteCompression from 'vite-plugin-compression'
import { createHtmlPlugin } from 'vite-plugin-html'
import vueJsx from '@vitejs/plugin-vue-jsx'
import OptimizationPersist from 'vite-plugin-optimize-persist'
import PkgConfig from 'vite-plugin-package-config'
import Inspect from 'vite-plugin-inspect'

/**
 * val值是否为字符串'true'
 *
 * @param   {string}  val  [val description]
 *
 * @return  {[type]}       [return description]
 */
function envStrValIsTrue(val: string | undefined | null) {
  return val === 'true'
}
const pathSrc = path.resolve(__dirname, 'src')
// https://vitejs.dev/config/
export default ({ command, mode }: ConfigEnv): UserConfigExport => {
  const root = process.cwd()
  // 读取.env中配置的环境变量
  const env = loadEnv(mode, root)
  console.log('执行命令: ', command, ', env配置文件数据: ', env)
  let viteMockServeInjectCode = ''
  // 是否使用mock数据进行构建
  if (envStrValIsTrue(env.VITE_BUILD_ENABLE_MOCK)) {
    viteMockServeInjectCode = `
      import { setupProdMockServer } from '../_createProductionServer';

      setupProdMockServer();
      `
  }
  // 其他可选插件
  const otherPlugins: (PluginOption | PluginOption[])[] = []
  if (envStrValIsTrue(env.VITE_PACKAGE_ANALYZER)) {
    // 启用包分析
    otherPlugins.push(
      visualizer({
        filename: './node_modules/.cache/visualizer/stats.html',
        open: true,
        gzipSize: true,
        brotliSize: true,
      })
    )
  }
  if (envStrValIsTrue(env.VITE_ENABLE_GZIP)) {
    // 启用gzip
    otherPlugins.push(viteCompression())
  }
  if (command === 'serve') {
    otherPlugins.push(Inspect())
  }

  const elementPlusStyleType = 'sass'
  return {
    plugins: [
      vue(),
      vueJsx(),
      eslintPlugin({ cache: false }),
      viteSvgIcons({
        // 指定需要缓存的图标文件夹
        iconDirs: [path.resolve(process.cwd(), 'src/assets/svg')],
        // 指定symbolId格式
        symbolId: 'icon-[dir]-[name]',
      }),
      viteMockServe({
        // default
        mockPath: 'mock',
        watchFiles: true,
        localEnabled: true,
        prodEnabled: envStrValIsTrue(env.VITE_BUILD_ENABLE_MOCK),
        injectCode: viteMockServeInjectCode,
      }),
      AutoImport({
        dts: path.resolve(pathSrc, 'auto-imports.d.ts'),
        resolvers: [ElementPlusResolver({ importStyle: elementPlusStyleType })],
      }),
      Components({
        // dirs 指定组件所在位置，默认为 src/components
        // 可以让我们使用自己定义组件的时候免去 import 的麻烦
        dirs: ['src/components/'],
        dts: path.resolve(pathSrc, 'components.d.ts'),
        resolvers: [ElementPlusResolver({ importStyle: elementPlusStyleType })],
      }),
      ElementPlusThemePlugin({
        themes: [
          {
            code: 'custom-theme',
            themeVarFilePath: '/themes/custom-theme.scss',
          },
        ],
      }),
      createHtmlPlugin({
        minify: true,
        /**
         * 在这里写entry后，你将不需要在`index.html`内添加 script 标签，原有标签需要删除
         * @default src/main.ts
         */
        entry: 'src/main.ts',
        /**
         * 需要注入 index.html ejs 模版的数据
         */
        inject: {
          data: {
            title: 'vue3项目',
          },
        },
      }),
      PkgConfig(),
      OptimizationPersist(),
      ...otherPlugins,
    ],
    css: {
      // 🔥此处添加全局scss🔥
      preprocessorOptions: {
        scss: {
          // 避免出现: build时的 @charset 必须在第一行的警告
          charset: false,
          additionalData: '@use "@/assets/scss/_var.scss" as *;',
        },
      },
    },
    build: {
      rollupOptions: {
        output: {
          manualChunks: (id: string, { getModuleInfo }) => {
            if (
              id.indexOf('node_modules/vue') >= 0 ||
              id.indexOf('node_modules/@vue') >= 0 ||
              id.indexOf('node_modules/vue-router') >= 0 ||
              id.indexOf('node_modules/pinia') >= 0 ||
              id.indexOf('node_modules/axios') >= 0
            ) {
              // vue, vue-rotuer, pinia, axios, vueuse, vue-request 单独打为一个js打包
              return 'vue_vue-router_pinia-axios'
            }
            if (
              id.indexOf('node_modules/@element-plus/icons-vue') >= 0 ||
              id.indexOf('node_modules/element-plus') >= 0
            ) {
              // element-plus 单独打为一个js打包
              return 'element-plus'
            } else if (id.indexOf('node_modules') >= 0) {
              // 其他第三方包，全部放入vendor
              return 'vendor'
            }
            // 这里还可以优化下, 将多处引用的service,store, util都单独提取到common文件
            const reg = /(.*)\/src\/components\/(.*)/
            if (reg.test(id)) {
              const importersLen = getModuleInfo(id)?.importers.length
              // 被多处引用
              if (importersLen && importersLen > 1) {
                return 'common'
              }
            }
          },
        },
      },
    },
    resolve: {
      alias: {
        '@': path.resolve(__dirname, 'src'),
        components: path.resolve(__dirname, 'src/components'),
        layouts: path.resolve(__dirname, 'src/layouts'),
        pages: path.resolve(__dirname, 'src/pages'),
        utils: path.resolve(__dirname, 'src/utils'),
        assets: path.resolve(__dirname, 'src/assets'),
        store: path.resolve(__dirname, 'src/store'),
      },
    },
  }
}
